{
const appURLFacts = getAppURLFactsFromRequestURL(req.originalUrl);
const { basePath, baseDomain } = appURLFacts;
const baseURL = basePath.replace(/\/$/, '');
const baseHref = baseDomain + baseURL;
const loadingPromise = getWebpackCompiledRootComponentForSSR();
const hasNotAcknowledgedPoliciesPromise = hasAnyNotAcknowledgedPolicies(
viewer.id,
baseLegalPolicies,
);
let initialNavInfo;
try {
initialNavInfo = navInfoFromURL(req.url, {
now: currentDateInTimeZone(viewer.timeZone),
});
} catch (e) {
throw new ServerError(e.message);
}
const calendarQuery = {
startDate: initialNavInfo.startDate,
endDate: initialNavInfo.endDate,
filters: defaultCalendarFilters,
};
const messageSelectionCriteria = { joinedThreads: true };
const initialTime = Date.now();
const assetInfoPromise = getAssetInfo();
const threadInfoPromise = fetchThreadInfos(viewer);
const messageInfoPromise = fetchMessageInfos(
viewer,
messageSelectionCriteria,
defaultNumberPerThread,
);
const entryInfoPromise = fetchEntryInfos(viewer, [calendarQuery]);
const currentUserInfoPromise = fetchCurrentUserInfo(viewer);
const userInfoPromise = fetchKnownUserInfos(viewer);
const sessionIDPromise = (async () => {
if (viewer.loggedIn) {
await setNewSession(viewer, calendarQuery, initialTime);
}
return viewer.sessionID;
})();
const threadStorePromise = (async () => {
const [{ threadInfos }, hasNotAcknowledgedPolicies] = await Promise.all([
threadInfoPromise,
hasNotAcknowledgedPoliciesPromise,
]);
return { threadInfos: hasNotAcknowledgedPolicies ? {} : threadInfos };
})();
const messageStorePromise = (async () => {
const [
{ threadInfos },
{ rawMessageInfos, truncationStatuses },
hasNotAcknowledgedPolicies,
] = await Promise.all([
threadInfoPromise,
messageInfoPromise,
hasNotAcknowledgedPoliciesPromise,
]);
if (hasNotAcknowledgedPolicies) {
return {
messages: {},
threads: {},
local: {},
currentAsOf: 0,
};
}
const { messageStore: freshStore } = freshMessageStore(
rawMessageInfos,
truncationStatuses,
mostRecentMessageTimestamp(rawMessageInfos, initialTime),
threadInfos,
);
return freshStore;
})();
const entryStorePromise = (async () => {
const [{ rawEntryInfos }, hasNotAcknowledgedPolicies] = await Promise.all([
entryInfoPromise,
hasNotAcknowledgedPoliciesPromise,
]);
if (hasNotAcknowledgedPolicies) {
return {
entryInfos: {},
daysToEntries: {},
lastUserInteractionCalendar: 0,
};
}
return {
entryInfos: _keyBy('id')(rawEntryInfos),
daysToEntries: daysToEntriesFromEntryInfos(rawEntryInfos),
lastUserInteractionCalendar: initialTime,
};
})();
const userStorePromise = (async () => {
const [userInfos, hasNotAcknowledgedPolicies] = await Promise.all([
userInfoPromise,
hasNotAcknowledgedPoliciesPromise,
]);
return {
userInfos: hasNotAcknowledgedPolicies ? {} : userInfos,
inconsistencyReports: [],
};
})();
const navInfoPromise = (async () => {
const [{ threadInfos }, messageStore, currentUserInfo, userStore] =
await Promise.all([
threadInfoPromise,
messageStorePromise,
currentUserInfoPromise,
userStorePromise,
]);
const finalNavInfo = initialNavInfo;
const requestedActiveChatThreadID = finalNavInfo.activeChatThreadID;
if (
requestedActiveChatThreadID &&
!threadIsPending(requestedActiveChatThreadID) &&
!threadHasPermission(
threadInfos[requestedActiveChatThreadID],
threadPermissions.VISIBLE,
)
) {
finalNavInfo.activeChatThreadID = null;
}
if (!finalNavInfo.activeChatThreadID) {
const mostRecentThread = mostRecentlyReadThread(
messageStore,
threadInfos,
);
if (mostRecentThread) {
finalNavInfo.activeChatThreadID = mostRecentThread;
}
}
if (
finalNavInfo.activeChatThreadID &&
threadIsPending(finalNavInfo.activeChatThreadID) &&
finalNavInfo.pendingThread?.id !== finalNavInfo.activeChatThreadID
) {
const pendingThreadData = parsePendingThreadID(
finalNavInfo.activeChatThreadID,
);
if (
pendingThreadData &&
pendingThreadData.threadType !== threadTypes.SIDEBAR &&
currentUserInfo.id
) {
const { userInfos } = userStore;
const members = [...pendingThreadData.memberIDs, currentUserInfo.id]
.map(id => {
const userInfo = userInfos[id];
if (!userInfo || !userInfo.username) {
return undefined;
}
const { username } = userInfo;
return { id, username };
})
.filter(Boolean);
const newPendingThread = createPendingThread({
viewerID: currentUserInfo.id,
threadType: pendingThreadData.threadType,
members,
});
finalNavInfo.activeChatThreadID = newPendingThread.id;
finalNavInfo.pendingThread = newPendingThread;
}
}
return finalNavInfo;
})();
const currentAsOfPromise = (async () => {
const hasNotAcknowledgedPolicies = await hasNotAcknowledgedPoliciesPromise;
return hasNotAcknowledgedPolicies ? 0 : initialTime;
})();
const pushApiPublicKeyPromise = (async () => {
const pushConfig = await getWebPushConfig();
if (!pushConfig) {
if (process.env.NODE_ENV !== 'development') {
console.warn('keyserver/secrets/web_push_config.json should exist');
}
return null;
}
return pushConfig.publicKey;
})();
const { jsURL, fontsURL, cssInclude, olmFilename, sqljsFilename, opaqueURL } =
await assetInfoPromise;
// prettier-ignore
res.write(html`
${getTitle(0)}
${cssInclude}
`);
const Loading = await loadingPromise;
const reactStream = renderToNodeStream();
reactStream.pipe(res, { end: false });
await waitForStream(reactStream);
res.write(html`
`);
}
-export { websiteResponder };
+const inviteSecretRegex = /^[a-z0-9]+$/i;
+
+function inviteResponder(req: $Request, res: $Response) {
+ const { secret } = req.params;
+ const userAgent = req.get('User-Agent');
+ const detectionResult = detectBrowser(userAgent);
+ let redirectUrl = stores.appStoreUrl;
+ if (detectionResult.os === 'Android OS') {
+ const isSecretValid = inviteSecretRegex.test(secret);
+ const referrer = isSecretValid
+ ? `&referrer=${encodeURIComponent(`utm_source=invite/${secret}`)}`
+ : '';
+ redirectUrl = `${stores.googlePlayUrl}${referrer}`;
+ }
+ res.writeHead(301, {
+ Location: redirectUrl,
+ });
+ res.end();
+}
+
+export { websiteResponder, inviteResponder };